home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
007
/
vtkerma1.arc
/
MSSERV.ASM
< prev
Wrap
Assembly Source File
|
1986-02-13
|
28KB
|
1,111 lines
PAGE 59, 132
TITLE MSSERV -- Module to handle all Server functions
; Update 20 Jan 86
IF1
%OUT >> Starting pass 1
ELSE
%OUT >> Starting pass 2
ENDIF
PUBLIC Logout, Bye, Finish, Remote, Get, Server, Enter_Server
INCLUDE MsDefs.H
DataS SEGMENT PUBLIC 'DataS'
EXTRN data:byte, flags:byte, trans:byte, pack:byte, curchk:byte
EXTRN fcb:byte, Data_2:BYTE, CurDsk:BYTE
remcmd DB 0 ; Remote command to be executed. [21c]
rempac DB 0 ; Packet type: C (host) or G (generic). [21c]
ermes7 DB 'Unable to Receive Initiate$'
erms18 DB '? Unable to tell host that session is finished',cr,lf,'$'
erms19 DB '? Unable to tell host to logout',cr,lf,'$'
erms21 DB '? Unable to tell host to execute command',cr,lf,'$' ; [21c]
erms70 DB '? Unable to send INIT (I) packet',cr,lf,'$'
infms1 DB cr,' Server: Waiting for request$'
infms2 DB cr,' Getting: Waiting for file$'
infms3 DB cr,' Getting: Sending request to remote server$'
remms1 DB 'Remote '
Program_name
db ': Unknown server command$'
remms2 DB 'Remote '
Program_name
db ': Illegal file name$'
remms3 DB 'Remote '
Program_name
db ': Unknown generic server command$'
remms4 DB 'Remote '
Program_name
db ': Unable to change directories$'; [jrd]
pass DB 'Password: $' ; When changing remote directories
crlf DB cr,lf,'$'
tmp DB ?,'$'
temp DW 0
oloc DW 0 ; Original buffer location. [21c]
osiz DW 0 ; Original buffer size. [21c]
inpbuf DW 0 ; Pointer to input buffer. [21c]
cnt DW 0
delinp DB BS,BS,BS,' ',BS,BS,BS,'$' ; When DEL key is used. [21d]
clrspc DB ' ', Bs, '$' ; Clear space
srvchr DB 'SRGIE' ; server cmd characters
srvfln EQU $-srvchr ; length of tbl
srvfun DW srvsnd,srvrcv,srvgen,srvini,RSkp
remhlp DB cr,lf,' CWD connect to a directory' ; [21c start]
DB cr,lf,' DELETE a file'
DB cr,lf,' DIRECTORY listing'
DB cr,lf,' HELP'
DB cr,lf,' HOST command'
DB cr,lf,' SPACE in a directory'
DB cr,lf,' TYPE a file$' ; [21c end]
remtab DB 7
mkeyw 'CWD',remcwd
mkeyw 'DELETE',remdel
mkeyw 'DIRECTORY',remdir
mkeyw 'HELP',remhel
mkeyw 'HOST',remhos
mkeyw 'SPACE',remdis
mkeyw 'TYPE',remtyp
remfnm DB ' Remote Source File: $'
lclfnm DB ' Local Destination File: $'
filhlp DB ' File name to receive as$'
filmsg DB ' Remote file specification or confirm with carriage return$'
frem DB ' Name of file on remote system$'
genmsg DB ' Enter text to be sent to remote server$'
SrvBuf DB 80H DUP(?)
DataS ENDS
Code SEGMENT PUBLIC
EXTRN comnd:near, spack:near, RPack:near, init:near
EXTRN SerIni:NEAR, read2:near, rpar:near, spar:near
EXTRN rin21:near, rfile3:near, error1:near, clrfln:near
EXTRN dodel:near, clearl:near, dodec: near, doenc:near, PrtScr:NEAR
EXTRN packlen:near, send11:near, errpack:near, init1:near
EXTRN NAK:NEAR, rrinit:near, Error:near, Prompt:NEAR, Read1:NEAR
EXTRN Close_transfer_screen:NEAR, Show_retries:NEAR
EXTRN Do_CXZ_mode_line:NEAR, Show_error:NEAR, Show_status:NEAR
ASSUME cs:Code, ds:DataS
; LOGOUT - tell remote KERSRV to logout
LOGOUT PROC
mov ah,cmcfm
call comnd ; Get a confirm
jmp r
mov al, flags.remflg ; Pick up current value of remote flag
push ax ; Save it
mov flags.remflg, 1 ; Force us into remote mode for LOGOUT command
call logo
nop
nop
nop
pop ax
mov flags.remflg, al ; Restore original value
jmp rskp
LOGOUT ENDP
LOGO PROC
mov pack.numtry,0 ; Initialize count
mov pack.numrtr,0 ; No retries yet
call serini ; Initialize port. [14]
mov ah,trans.chklen ; Don't forget the checksum length
mov curchk,ah
mov trans.chklen,1 ; Use one char for server functions
logo1: cmp pack.state,'A' ; Did user type a ^C?
je logo2x ; Yes just leave
mov ah,pack.numtry
cmp ah,maxtry ; Too many times?
js logo3 ; No, try it
logo2: mov ah,prstr
mov dx,offset erms19
int dos
logo2x: mov ah,curchk
mov trans.chklen,ah ; Restore value
ret
logo3: inc pack.numtry ; Increment number of tries
mov pack.argblk,0 ; Packet number zero
mov pack.argbk1,1 ; One piece of data
mov bx,offset data
mov ah,'L'
mov [bx],ah ; Logout the remote host
mov cx,1 ; One piece of data
call doenc ; Do encoding
mov ah,'G' ; Generic command packet
call spack
jmp SHORT logo2 ; Tell user and die
nop
call RPack ; Get ACK (w/o screen msgs.)
jmp SHORT logo1 ; Go try again
nop
push ax
call dodec ; Decode packet
mov ah,curchk
mov trans.chklen,ah ; Restore value
pop ax
cmp ah,'Y' ; ACK?
jne logo4
jmp rskp
logo4: cmp ah,'E' ; Error packet?
jnz logo1 ; Try sending the packet again
jmp error1
LOGO ENDP
; FINISH - tell remote KERSRV to exit
FINISH PROC
mov ah,cmcfm ; Parse a confirm
call comnd
jmp r
mov al, flags.remflg ; Pick up current value of remote flag
push ax ; Save it
mov flags.remflg, 1 ; Force us into remote mode for LOGOUT command
mov pack.numtry,0 ; Initialize count
mov pack.numrtr,0 ; No retries yet
call serini ; Initialize port. [14]
mov ah,trans.chklen ; Don't forget the checksum length
mov curchk,ah
mov trans.chklen,1 ; Use one char for server functions
fin1: cmp pack.state,'A' ; ^C typed?
je fin2x
mov ah,pack.numtry
cmp ah,maxtry ; Too many times?
js fin3 ; Nope, try it
fin2: mov ah,prstr
mov dx,offset erms18
int Dos
fin2x: mov ah,curchk
mov trans.chklen,ah ; Restore value
jmp SHORT fin5 ; Go home
fin3: inc pack.numtry ; Increment number of tries
mov pack.argblk,0 ; Packet number zero
mov pack.argbk1,1 ; One piece of data
mov bx,offset data
mov ah,'F'
mov [bx],ah ; Finish running Kermit
mov cx,1 ; One piece of data
call doenc ; Do encoding
mov ah,'G' ; Generic command packet
call spack
jmp SHORT fin2 ; Tell user and die
nop
call RPack ; Get ACK (w/o screen stuff)
jmp SHORT fin1 ; Go try again
nop
push ax
call dodec ; Decode data
mov ah,curchk
mov trans.chklen,ah ; Restore value
pop ax
cmp ah,'Y' ; Got an ACK?
jnz fin4
jmp SHORT fin5 ; Yes, then we're done
fin4: cmp ah,'E' ; Error packet?
jnz fin1 ; Try sending it again
call error1
fin5: pop ax
mov flags.remflg, al ; Restore original value
jmp rskp
FINISH ENDP
; BYE command - tell remote KERSRV to logout & exits to DOS
BYE PROC
mov ah,cmcfm ; Parse a confirm
call comnd
jmp r
mov al, flags.remflg ; Pick up current value of remote flag
push ax ; Save it
mov flags.remflg, 1 ; Force us into remote mode for LOGOUT command
call logo ; Tell the mainframe to logout
jmp SHORT Bye_1 ; Don't exit yet
nop ; 3 bytes
mov flags.extflg,1 ; Set exit flag
Bye_1: pop ax
mov flags.remflg, al ; Restore original value
jmp rskp
BYE ENDP
; Tell remote server to send the specified file(s)
Get PROC
mov flags.droflg,0 ; Reset flags from fn parsing
mov flags.nmoflg,0 ; Reset flags from fn parsing
mov flags.cxzflg,0 ; no ctl-c typed yet..
mov bx,offset data ; Where to put text. [8 start]
mov dx,offset filmsg ; In case user needs help
mov ah,cmtxt
call comnd ; Get text or confirm
jmp RSkp ; Failed
cmp ah,0 ; Read in any chars?
jne get4 ; Yes, then OK
; Empty line, ask for file names
Get1: mov dx,offset remfnm ; ask for remote first
call prompt
mov bx,offset data
mov dx,offset frem
mov ah,cmtxt
call comnd ; get a line of text
jmp RSkp
cmp flags.cxzflg,'C' ; ctl-C typed?
jne get2 ; no, continue
jmp rskp
get2: cmp ah,0
je get1 ; Ignore empty lines
mov bl,ah
mov bh,0
mov byte ptr data[bx],'$' ; terminate name for printing
mov pack.argbk1,bx ; remember length here
mov dx,offset lclfnm
call prompt
mov ah,cmifi
mov bx,offset filhlp
mov dx,offset fcb
call comnd
jmp RSkp
mov ah,cmcfm
call comnd
jmp r
cmp flags.cxzflg,'C' ; control-C typed?
jne get3 ; no, keep going
jmp rskp
get3: mov flags.nmoflg,1 ; remember changed name
jmp short get5
get4: mov al,ah
mov ah,0
mov pack.argbk1,ax ; Remember number of chars we read
mov byte ptr [bx],'$' ; use for printing
get5: push cx ; Save regs
push si
push di
mov cx, 5Ah ; Size of the Data and Data_2 buffers
mov si, OFFSET Data ; Copy from ...
mov di, OFFSET Data_2 ; Copy to ...
rep movsb ; Copy from Data to Data_2
mov cx, Pack.ArgBk1 ; Pick up size of data packet
mov Temp, cx ; Save it for a minute
pop di ; Restore regs
pop si
pop cx
call Init ; Clear line and initialize buffers
mov dx, OFFSET InfMs3 ; Say we are sending a request for the file
call Show_status ; Display the message
call IPack ; Send our INITIATE params to the server
jmp Get_error ; Couldn't do it
push cx ; Save regs
push si
push di
mov cx, Temp ; Get back size of data packet
mov Pack.ArgBk1, cx ; Restore it
mov cx, 5Ah ; Size of the Data and Data_2 buffers
mov si, OFFSET Data_2 ; Copy from ...
mov di, OFFSET Data ; Copy to ...
rep movsb ; Copy from Data_2 back to Data area
pop di ; Restore regs
pop si
pop cx
call serini ; Initialize port
mov pack.pktnum,0 ; Set packet number to zero
mov pack.numtry,0 ; Initialize count
mov pack.numpkt,0 ; Set the number of packets to zero
mov pack.numrtr,0 ; No retries yet
mov pack.state,'R' ; this is what state will soon be..
cmp flags.remflg,0 ; remote mode?
jne get6 ; yes, don't print anything
mov dx, OFFSET InfMs2 ; Say we are waiting for the file
call Show_status ; Display the message
call clrfln ; Prepare to print filename
mov ah,prstr
mov dx,offset data ; Print file name
int dos
get6: call init1 ; init buffers
mov cx,pack.argbk1 ; Data size
call doenc ; Encode data
mov ah,trans.chklen ; Don't forget the checksum length
mov curchk,ah
mov trans.chklen,1 ; Use one char for server functions
get7: cmp pack.state,'A' ; Did user type a ^C?
je get9 ; Yes - just return to main loop
call Show_retries ; Give a progress report
cmp pack.numtry, imxtry ; Too many times?
jb get10 ; Nope, try it
Get8: mov dx, OFFSET ErMes7 ; Unable to Receive Initiate
jmp SHORT Get8a ; Joint common code
Get_error:
mov dx, OFFSET erms70 ; Message to say we couldn't send INIT packet
Get8a: call Show_error
Get9: call Close_transfer_screen ; Erase mode line, go to lower left
mov ah,curchk
mov trans.chklen,ah ; Restore value
jmp rskp ; Go home
get10: inc pack.numtry ; Increment number of tries
mov pack.argblk,0 ; Start at packet zero
mov ah,'R' ; Receive init packet
call spack ; Send the packet
jmp SHORT get8 ; Tell user we can't do it
nop
call RPack ; Get ACK (w/o screen stuff)
jmp SHORT Get11 ; Got a NAK - try again
nop
push ax
mov ah,curchk
mov trans.chklen,ah ; Restore value
pop ax
mov pack.argbk2,ax ; this is where rinit wants pkt type if getting
mov flags.getflg,1 ; "Get" as vs "Receive"
jmp Read1 ; go join read code
Get11: inc Pack.NumRtr ; Bump number of retries
jmp Get7 ; Go try again
GET ENDP
; Server command
Server PROC
mov ah,cmcfm
call comnd
jmp r
; Pre-confirmed entry to Server Mode, enter from Terminal Emulation Mode
Enter_Server:
push es
mov ax,ds
mov es,ax ; address data segment
mov al,flags.remflg ; get remote flag
push ax ; preserve for later
; mov flags.remflg,1 ; set remote if server (Turn on server screen)
mov Flags.NmOFlg, 0 ; Clear the name override flag
; (CMIFI leaves it set)
mov Flags.DrOFlg, 0 ; Likewise for drive override
call Init ; Clear screen, display template & mode line
call serini ; Init serial port
; should reset to default parms here..
; should increase timeout interval
Serv1: mov trans.chklen,1 ; checksum len = 1
mov pack.pktnum,0 ; pack number resets to 0
mov pack.numtry,0 ; no retries yet
mov dx, OFFSET infms1 ; Message is "Server: Waiting for request"
call Show_status ; Display status
call rpack ; Get a packet
jmp SHORT Serv2 ; No good, NAK and continue
nop
jmp SHORT Serv3 ; Try to figure this out
PUBLIC Serv2, Serv3
serv2: cmp Flags.CxzFlg, 'C' ; Control-C?
je Serv5 ; Yes
call nak ; nak the packet
jmp serv1 ; and keep reading packets
serv3: mov di,offset srvchr ; server characters
mov cx,srvfln ; length of string
mov al,ah ; packet type
repne scasb ; hunt for it
je serv4 ; we know this one, go handle it
mov bx,offset remms1 ; else give a message
call errpack ; back to local kermit
jmp serv1 ; and keep looking for a cmd
serv4: sub di,offset srvchr+1 ; find offset, +1 for pre-increment
shl di,1 ; convert to word index
call srvfun[di] ; call the appropriate handler
jmp serv5 ; someone wanted to exit..
call Do_CXZ_mode_line ; Called rtn trashed the mode line
jmp serv1 ; Keep going for more cmds
%OUT >> About half way through source file
Serv5: call Close_transfer_screen ; Close out the file transfer screen
pop ax ; get this off stack
mov flags.remflg,al ; restore old flag
pop es ; restore register
jmp rskp ; and return
Server ENDP
; *** Server Commands ***
; srvsnd - receives a file that the local kermit is sending
srvsnd PROC
mov bx,offset data
call spar ; parse the send-init packet
call packlen ; figure max packet
mov bx,offset data
call rpar ; make answer for them
mov al,ah ; length of packet
mov ah,0
mov pack.argbk1,ax ; store length for spack
mov ah,'Y' ; ack
call spack ; answer them
jmp rskp ; can't answer, forget this
call rrinit ; init variables for init
inc pack.pktnum ; count the send-init packet
mov pack.state,'F' ; expecting file name about now
call Read1 ; and join read code
nop
nop
nop ; ignore errors
jmp rskp ; and return for more
SrvSnd endp
; srvrcv - send a file that they're receiving
srvrcv PROC
call DoDec ; Fix up the encoded filename
mov si,offset data ; this should be it after decoding
mov di,offset fcb ; this is where filename goes
mov al,1 ; skip leading separators
mov ah,prsfcb ; parse an fcb
int dos ; let dos do the work
cmp al,0ffh ; invalid?
jne srvrc1 ; no, keep going
mov bx,offset remms2 ; complain
call errpack ; that we can't find it
jmp rskp ; and return
SrvRc1: cmp al, 1 ; Wildcards used?
jne SrvRc2 ; No
mov Flags.WldFlg, 0FFh ; Flag the wildcard
SrvRc2: mov pack.state,'R' ; remember state
call send11 ; this should send it
nop
nop
nop
jmp rskp ; return in any case
SrvRcv ENDP
PUBLIC SrvGen
; srvgen - generic server commands
; We only support Logout and Finish right now
srvgen PROC
call DoDec ; Decode the data packet
mov al,data ; get 1st packet char
cmp al, 'C' ; Remote CWD (Change Working Directory)?
jne srvge0 ; No
call Remote_CWD ; Use other routine to do the CWD
jmp RSkp ; Return normally
srvge0: cmp al,'F' ; maybe finish?
je srvge1 ; yup, handle
cmp al,'L' ; logout?
jne srvge2 ; no
srvge1: mov pack.argbk1,0 ; 0-length data
mov ah,'Y'
call spack ; ack it
nop
nop
nop ; *** ignore error?
ret ; and return to signal exit
srvge2: mov bx,offset remms3
call errpack
jmp rskp
srvgen endp
PUBLIC Remote_CWD
; Do a REMOTE CWD for the other Kermit
Remote_CWD PROC
mov cl, data+1 ; get the filename byte count
sub cl, ' ' ; ascii to numeric
cmp cl, 0 ; anything there?
jle srcwd3 ; le = no, an error
sub ch, ch ; set up counter
mov si, OFFSET data+2 ; received dir spec, from rpack
mov di, OFFSET srvbuf ; destination
rep movsb ; copy data to srvbuf, cx chars worth
mov BYTE PTR [di],0 ; plant terminator
mov dx, OFFSET srvbuf ; for DOS
mov ax, dx ; dir spec pointer for isfile
cmp BYTE PTR [di-1], ':' ; did user just type A: or similar?
je srcwd1 ; e = yes, so skip directory part
mov ah, chdir ; want to do change dir
int Dos
jnc srcwd1 ; nc = ok
srcwd3: mov bx, OFFSET remms4 ; an error.
jmp errpack ; send the bad news, ret from there
srcwd1: mov dl, data+3 ; see if drive given (look for :)
cmp dl, ':'
jne srcwd2 ; ne = no drive
mov dl, data+2
and dl, 5fH ; convert to upper case
sub dl, 'A' ; count A = 0 for seldsk call
mov ah, seldsk
int Dos ; change disks
jc srcwd3 ; c = an error
inc dl ; now make A = 1 etc internally
mov curdsk, dl ; and update internal current disk code
srcwd2: mov ah, 'Y' ; return an ack
mov pack.argbk1, 0 ; no data
call spack ; Send the packet
nop
nop
nop
ret ; Done here
Remote_CWD ENDP
; srvini - init parms based on init packet
srvini PROC
mov bx,offset data
call spar ; parse info
call packlen ; this should really be part of spar, but..
mov bx,offset data
call rpar ; get receive info
mov al,ah
mov ah,0
mov pack.argbk1,ax ; set size of return info
mov ah,'Y'
call spack ; send the packet off
jmp rskp
jmp rskp ; and go succeed
srvini endp
; This is the REMOTE command. [21c]
REMOTE PROC
mov dx,offset remtab ; Parse a keyword from the REMOTE table
mov bx,offset remhlp
mov ah,cmkey
call comnd
jmp r
mov al, flags.remflg ; Pick up current value of remote flag
push ax ; Save it
mov flags.remflg, 1 ; Force us into remote mode for LOGOUT command
call bx ; Call the appropriate routine
nop ; Tolerate skip and non-skip returns
nop
nop
pop ax
mov flags.remflg, al ; Restore original value
jmp rskp
REMOTE ENDP
; REMDIS - Get disk usage on remote system. [21c]
REMDIS PROC
mov remcmd,'U' ; Disk usage command
mov rempac,'G' ; Packet type = generic
jmp genric ; Execute generic Kermit command
REMDIS ENDP
; REMHEL - Get help about remote commands. [21c]
REMHEL PROC
mov remcmd,'H' ; Help.....
mov rempac,'G' ; Packet type = generic
jmp genric ; Execute generic Kermit command
REMHEL ENDP
; REMTYP - Print a remote file. [21c]
REMTYP PROC
mov remcmd,'T' ; Type the file
mov rempac,'G' ; Packet type = generic
jmp genric
REMTYP ENDP
; REMHOS - Execute a remote host command. [21c]
REMHOS PROC
mov remcmd,' ' ; Don't need one
mov rempac,'C' ; Packet type = remote command
jmp genric
REMHOS ENDP
; REMDIR - Do a directory. [21c]
REMDIR PROC
mov remcmd,'D'
mov rempac,'G' ; Packet type = generic
jmp genric
REMDIR ENDP
; REMDEL - Delete a remote file. [21c]
REMDEL PROC
mov remcmd,'E'
mov rempac,'G' ; Packet type = generic
jmp genric
REMDEL ENDP
; REMCWD - Change remote working directory. [21c]
REMCWD PROC
mov remcmd,'C'
mov rempac,'G' ; Packet type = generic
; jmp genric
REMCWD ENDP
; GENRIC - Send a generic command to a remote Kermit server. [21c]
GENRIC PROC
mov bx,offset SrvBuf ; Where to put the text
cmp rempac,'C' ; Remote host command?
je genra ; Yes, leave as is
add bx,2 ; Leave room for type and size
genra: mov ah,cmtxt ; Parse arbitrary text up to a CR
mov dx,offset genmsg ; In case they want text
call comnd
jmp r
mov al,ah ; Don't forget the size
mov ah,0
mov cnt,ax ; Save it here
cmp rempac,'C' ; Remote host command?
jne genrb ; No, skip this part
call ipack
jmp genr2
mov pack.numtry,0
mov ah,trans.chklen
mov curchk,ah ; Save desired checksum length
mov trans.chklen,1 ; Use 1 char for server functions
mov pack.numrtr,0 ; No retries yet
jmp genr1 ; Send the packet
genrb: mov ax,cnt
cmp ax,0 ; Any data?
je genr0 ; Nope
mov ah,al ; Don't overwrite the real count value
add ah,32 ; Do the char function
mov temp,bx ; Remember where we are
mov bx,offset SrvBuf+1 ; Size of remote command
mov [bx],ah
mov ah,0
inc al ; For the size field
cmp remcmd,'C' ; Change working directory?
jne genr0 ; No, so don't ask for password
mov cnt,ax ; Save here for a bit
mov ah,prstr
mov dx,offset pass ; Send along an optional password
int dos
mov bx,temp ; Where to put the password
push bx ; Is safe since subroutine never fails
inc bx ; Leave room for count field
call input ; Read in the password
mov temp,bx ; Remember end of data pointer
pop bx ; Where to put the size
cmp ah,0 ; No password given?
jne genrc
mov ax,cnt
jmp genr0a ; Then that's it
genrc: mov al,ah
add ah,32 ; Make it printable
mov [bx],ah ; Tell remote host the size
mov ah,0
push ax ; Remember the count
call clearl ; Clear to end-of-line
pop ax
inc al ; For second count value
add ax,cnt ; Total for both fields of input
genr0a: push ax ; Save ax
mov ah, PrStr ; Code to type a string
mov dx, OFFSET CrLf ; A CrLf
int Dos ; Type it
pop ax ; Get back ax
genr0: inc al ; For the char representing the command
mov pack.argbk1,ax ; Set the size
mov cnt,ax ; And remember it
mov pack.numtry,0 ; Initialize count
mov bx,offset SrvBuf ; Start of data buffer
mov ah,remcmd ; Command subtype
mov [bx],ah
call ipack ; Send init parameters
jmp SHORT genr2
nop ; Make it 3 bytes long
mov ah,trans.chklen
mov curchk,ah ; Save desired checksum length
mov trans.chklen,1 ; Use 1 char for server functions
mov pack.numrtr,0 ; No retries yet
genr1: cmp pack.state,'A' ; Did the user type a ^C?
je genr2x
mov ah,pack.numtry
cmp ah,maxtry ; Too many tries?
js genr3 ; Nope, keep trying
genr2: mov ah,prstr
mov dx,offset erms21 ; Print error msg and fail
int dos
genr2x: mov ah,curchk
mov trans.chklen,ah ; Restore
jmp rskp
genr3: push es ; Prepare to put string into packet
mov ax,ds
mov es,ax
mov si,offset SrvBuf ; Move from here
mov di,offset data ; to here
mov cx,cnt ; Move this many characters
rep movsb ; Perform the string move
pop es
mov ax,cnt
mov pack.argbk1,ax ; How much data to send
mov cx,ax ; Size of data
call doenc ; Encode it
inc pack.numtry ; Increment number of trials
mov pack.argblk,0 ; Packet number 0
mov ah,rempac ; Packet type
call spack ; Send the packet
jmp genr2 ; Tell user we can't do it
nop
call RPack ; Get ACK (w/o screen stuff)
jmp genr1 ; Got a NAK - try again
nop
push ax
mov ah,curchk
mov trans.chklen,ah ; Restore
pop ax
cmp ah,'Y' ; Is all OK?
jne genr4
cmp pack.argbk1,0 ; Any data in the ACK?
je genr31 ; Nope - just return
call dodec ; Decode data
mov ah,prstr
mov dx,offset crlf ; First go to a new line
int dos
mov di,offset data ; Where the reply is
mov cx,pack.argbk1 ; How much data we have
call prtscr ; Print it on the screen
mov ah,prstr
mov dx,offset crlf ; Go to a new line
int dos
mov ah,prstr
mov dx,offset crlf ; Go to a new line
int dos
genr31: jmp rskp ; And we're done
genr4: cmp ah,'X' ; Text packet?
je genr5
cmp ah,'S' ; Handling this like a file?
jne genr6
mov pack.state,'R' ; Set the state
mov bx,offset rin21 ; Where to go to
jmp genr51 ; Continue
genr5: mov pack.state,'F'
call dodec ; Decode data
mov bx,offset rfile3 ; Jump to here
PUBLIC genr4,genr5,genr51,genr6
genr51: mov tmp,ah ; Save packet type
mov flags.xflg,1 ; Remember we saw an "X" packet
mov pack.numtry,0
mov pack.numrtr,0
mov pack.numpkt,0
mov pack.pktnum,0
mov flags.cxzflg,0
mov ah,tmp ; Packet type
call bx ; Handle it almost like filename
call read2 ; Receive the rest
jmp r ; Oops, we failed
jmp rskp ; Done OK
genr6: cmp ah,'E' ; Error packet?
je genr6x
jmp genr1 ; Try again
genr6x: call dodec ; Decode data
call error1 ; Print the error messge
jmp rskp ; And return
GENRIC ENDP
; Send "I" packet with transmission parameters. [21c]
IPACK PROC NEAR
mov ah,trans.chklen
mov curchk,ah ; Initialize
call serini
mov pack.pktnum,0 ; Use packet number 0
mov pack.numtry,0 ; Number of retries
ipk0: cmp pack.state,'A' ; Did user type a ^C?
je ipk0x
cmp pack.numtry,imxtry ; Reached our limit?
jl ipk1
ipk0x: ret ; Yes, so we fail
ipk1: inc pack.numtry ; Save the updated number of tries
mov bx,offset data ; Get a pointer to our data block
call rpar ; Set up the parameter information
xchg ah,al
mov ah,0
mov pack.argbk1,ax ; Save the number of arguments
mov pack.argblk,0 ; Use packet number 0
mov ah,trans.chklen
mov curchk,ah ; Save real value
mov trans.chklen,1 ; One char for server function
mov ah,'I' ; "I" packet
call spack ; Send the packet
jmp ipk4
nop
call RPack ; Get a packet
jmp ipk4 ; Try again
nop
push ax
mov ah,curchk
mov trans.chklen,ah ; Reset
pop ax
cmp ah,'Y' ; ACK?
jne ipk3 ; If not try next
mov ax,pack.pktnum ; Get the packet number
cmp ax,pack.argblk ; Is it the right packet number?
je ipk2
jmp ipk0 ; If not try again
ipk2: mov ax,pack.argbk1 ; Get the number of pieces of data
mov bx,offset data ; Pointer to the data
call spar ; Read in the data
mov ah,trans.chklen
mov curchk,ah ; This is what we decided on
call packlen ; Get max send packet size. [21b]
mov pack.numtry,0 ; Reset the number of tries
jmp rskp
ipk3: cmp ah,'N' ; NAK?
je ipk0 ; Yes, try again
cmp ah,'E' ; Is it an error packet
je ipk3x
jmp ipk0 ; Trashed data
ipk3x: jmp rskp ; Other side doesn't know about "I" packet
ipk4: mov ah,curchk
mov trans.chklen,ah ; Reset
jmp ipk0 ; Keep trying
IPACK ENDP
; Returns in AH the count of characters read in
; in BX the updated pointer to the input buffer
INPUT PROC
mov cl,0 ; Keep a count
mov inpbuf,bx ; Where to put data
input0: mov ah,conin ; Read in a char
int dos
cmp al,CR ; Done with input?
jne input1
mov ah,cl ; Return count in AH
jmp r
input1: cmp al,BS ; Backspace?
je inpt11 ;
cmp al,DEL ; Or delete?
jne input3
call dodel ; Erase weird character
inpt11: dec cl ; Don't include in char count
cmp cl,0 ; Backspaced too much?
jns input2 ; No, is OK
push bx
call clearl
pop bx
mov ah,conout
mov dl,bell
int dos
mov cl,0
jmp input0
input2: dec bx ; 'Remove' from buffer
mov ah,prstr
mov dx,offset clrspc
int dos
jmp input0 ; Go get more
input3: cmp al,'U'-64 ; Control-U?
jne input4
mov ah,prstr
mov dx,offset pass+1
int dos
push bx
push cx
call clearl ; Blank out the line
pop cx
pop bx
mov cl,0 ; Reset count to zero
mov bx,inpbuf ; Start at head of buffer
jmp input0
input4: cmp al,0 ; Two character sequence?
jne input5
mov ah,conin
int dos ; Get second char
cmp al,83 ; Delete key?
je inpt40 ; Yup
cmp al,75 ; Backarrow key?
je inpt40
call dodel ; Erase weird character
jmp input0 ; And go on computing
inpt40: mov ah,prstr
mov dx,offset delinp ; Erase weird character
int dos
jmp inpt11 ; Remove the offending char
input5: mov [bx],al ; Add char to buffer
inc cl ; Include in count
inc bx
jmp input0
INPUT ENDP
; Jumping to this location is like retskp. It assumes the instruction
; after the call is a jmp addr
RSKP PROC NEAR
pop bp
add bp,3
push bp
; ret
RSKP ENDP
; Jumping here is the same as a ret
R PROC NEAR
ret
R ENDP
Code ENDS
END